package com.inibb.app.dao.api;

import java.io.Serializable;
import java.util.List;

import com.inibb.app.dao.criteria.Criteria;

/**
 * Interface represents implementation of generic DAO.
 *
 * @param <E> object's type, it must implements at least <code>IEntity</code>
 * @param <PK> primary key's type
 *
 * @since 1.0
 */
public interface IDao<E , PK extends Serializable> {

    /**
     * Retrieve an persisted object using the given id as primary key.
     *
     * @param id object's primary key
     * @return object
     */
    E load(PK id);

    /**
     * Retrieve an persisted object using the given id as primary key.
     *
     * Returns null if not found.
     *
     * @param id object's primary key
     * @return object
     */
    E get(PK id);


    /**
     * Retrieve all persisted objects with given parents.
     *
     * If parent is null, method returns root objects (with no parent).
     *
     * @param parent objects' parent
     * @return list of objects
     */
    List<E> get(IInheritable<E> parent);

    /**
     * Retrieve all persisted objects.
     *
     * @return list of objects
     */
    List<E> getAll();
    
    
    List<E> findByNamedQuery(String namedQuery);

    /**
     * Find objects comparing them with examplary object using all not-null properties.
     *
     * Properties <code>IEntity.id</code>, <code>IDefaultable.isDefault</code>, <code>IActivable.isActive</code> and <code>IHiddenable.isHidden</code> are ignored.
     *
     * @param example examplary object
     * @return list of objects
     */
    List<E> findByExample(E example);

    List<E> findByCriteria(Criteria criteria);
    
    int countByExample(E example);
    
    /**
     * Update all changes made to an object.
     *
     * @param object object
     */
    E merge(E object);

    /**
     * Insert all changes made to an object.
     *
     * @param object object
     */
    E persist(E object);
    
    
    /**
     * Remove an object by given id. Check if object is not default one.
     *
     * If entity implements <code>IHiddenable</code> then it is hidden instead of deleted.
     *
     * @param id object's pk
     * @throws UnsupportedOperationException - if entity is default one
     * @see IHiddenable
     */
    void delete(PK id) throws UnsupportedOperationException;


    /**
     * Remove an object. Check if object is not default one.
     *
     * If object implements <code>IHiddenable</code> then it is hidden instead of deleted.
     *
     * @param object object
     * @throws UnsupportedOperationException - if entity is default one
     * @see IHiddenable
     */
    void delete(E object) throws UnsupportedOperationException;

    /**
     * Remove objects. Check if all objects are not mark as default one.
     *
     * If objects implement <code>IHiddenable</code> then they are hidden instead of deleted.
     *
     * @param objects objects
     * @throws UnsupportedOperationException - if one of entities is default one
     * @see IHiddenable
     */
    void delete(E... objects) throws UnsupportedOperationException;

    /**
     * Delete all objects, including default one.
     *
     * If objects implement <code>IHiddenable</code> then they are hidden instead of deleted.
     *
     * @see IHiddenable
     */
    void deleteAll();

    /**
     * Refresh a persistant object that may have changed in another thread/transaction.
     *
     * @param entity transient entity
     */
    void refresh(E entity);

    /**
     * Write to database anything that is pending operation and clear it.
     */
    void flushAndClear();

    /**
     * Check whether the DAO represents <code>IActivable</code> implementation.
     *
     * @return true if DAO's object are activable
     * @see IActivable
     */
    public boolean isActivable();


    /**
     * Check whether the DAO represents <code>IHiddenable</code> implementation.
     *
     * @return true if DAO's object are hiddenable
     * @see IHiddenable
     */
    public boolean isHiddenable();

    /**
     * Check whether the DAO represents <code>IInheritable</code> implementation.
     *
     * @return true if DAO's object are inheritable
     * @see IInheritable
     */
    public boolean isInheritable();
    
    /**
     * to retrieve JPQL from pre-defined sqlt.xml file.
     * 
     * @param namespace - the namespace of the template
     * @param sqltId - the sql template id
     * @param criteria - the criteria for parameter resolving
     * @return templated jpql string.  
     */
    public String getJpqlTemplate(String namespace, String sqltId, Object criteria);
    
    /**
     * to retrieve Native SQL from pre-defined sqlt.xml file.
     * 
     * @param namespace - the namespace of the template
     * @param sqltId - the sql template id
     * @param criteria - the criteria for parameter resolving
     * @return templated native sql string.  
     */
    public String getNativeSqlTemplate(String namespace, String sqltId, Object criteria);
    
    /**
     * return unique result from a pre-defined native sql string.
     * 
     * @param namespace - the namespace of the template
     * @param sqltId - the sql template id
     * @param criteria - the criteria for parameter resolving
     * @return unique result
     */
    public Object queryNativeSqlForObject(String namespace, String sqltId, Object criteria);
    
    /**
     * return list result from a pre-defined native sql string.
     * 
     * @param namespace - the namespace of the template
     * @param sqltId - the sql template id
     * @param criteria - the criteria for parameter resolving
     * @return list of persistence object
     */
    public List queryNativeSqlForList(String namespace, String sqltId, Object criteria);
    
    /**
     * return single page list result from a pre-defined native sql string.
     * 
     * @param namespace - the namespace of the template
     * @param sqltId - the sql template id
     * @param criteria - the criteria for parameter resolving
     * @param startRow - first row of the page
     * @param pageSize - record count of the page
     * @return list of persistence object(in the form of object[])
     */
    public List queryNativeSqlForList(String namespace, String sqltId, Object criteria, int startRow, int pageSize);
    
    /**
     * return unique result from a pre-defined jpql string.
     * 
     * @param namespace - the namespace of the template
     * @param sqltId - the sql template id
     * @param criteria - the criteria for parameter resolving
     * @return unique result
     */
    public Object queryJpqlForObject(String namespace, String sqltId, Object criteria);
    
    /**
     * return list result from a pre-defined jpql string.
     * 
     * @param namespace - the namespace of the template
     * @param sqltId - the sql template id
     * @param criteria - the criteria for parameter resolving
     * @return list of persistence object
     */
    public List queryJpqlForList(String namespace, String sqltId, Object criteria);
    
    /**
     * return single page list result from a pre-defined jpql string.
     * 
     * @param namespace - the namespace of the template
     * @param sqltId - the sql template id
     * @param criteria - the criteria for parameter resolving
     * @param startRow - first row of the page
     * @param pageSize - record count of the page
     * @return list of persistence object
     */
    public List queryJpqlForList(String namespace, String sqltId, Object criteria, int startRow, int pageSize);
    
    
	public List queryNativeSqlForList(String namespace, String sqltId, Object[] criteria);

    
	public int executeNativeSqlUpdate(String namespace, String sqltId, Object criteria) ;
	
	public int executeJpqlUpdate(String namespace, String sqltId, Object criteria) ;
}
